﻿using Autofac;
using Autofac.Extras.DynamicProxy;

using EmployeeCard.Common;
using EmployeeCard.Common.Attributes;
using EmployeeCard.Common.Helper;
using EmployeeCard.Extensions.AOP;
using EmployeeCard.IRepository.Base;
using EmployeeCard.IServices;
using EmployeeCard.IServices.Base;
using EmployeeCard.Repository.Base;
using EmployeeCard.Services;
using EmployeeCard.Services.Base;

using System.Reflection;

namespace EmployeeCard.Extensions.ServiceExtensions
{
    public class AutofacMoudleManager : Autofac.Module
    {
        /// <summary>
        /// 重写autofac的load方法，在这里注册注入
        /// </summary>
        /// <param name="builder"></param>
        /// <exception cref="Exception"></exception>
        protected override void Load(ContainerBuilder builder)
        {
            var basePath = AppContext.BaseDirectory;
            //builder.RegisterType<AdvertisementServices>().As<IAdvertisementServices>();


            #region 带有接口层的服务注入

            var servicesDllFile = Path.Combine(basePath, "EmployeeCard.Services.dll");
            var repositoryDllFile = Path.Combine(basePath, "EmployeeCard.Repository.dll");

            if (!(File.Exists(servicesDllFile) && File.Exists(repositoryDllFile)))
            {
                var msg = "Repository.dll和service.dll 丢失，因为项目解耦了，所以需要先F6编译，再F5运行，请检查 bin 文件夹，并拷贝。";
                throw new Exception(msg);
            }


            // AOP 开关，如果想要打开指定的功能，只需要在 appsettigns.json 对应对应 true 就行。
            var cacheType = new List<Type>();
            if (AppSettings.app(new string[] { "AppSettings", "CachingAOP", "Enabled" }).ObjToBool())
            {
                // 注册缓存服务（不需要拦截器）
                builder.RegisterType<MemoryCaching>()
                       .As<ICaching>()
                       .SingleInstance();
                builder.RegisterType<BlogCacheAOP>();
                cacheType.Add(typeof(BlogCacheAOP));
            }

            if (AppSettings.app(new string[] { "AppSettings", "RedisAOP", "Enabled" }).ObjToBool())
            {
                builder.RegisterType<BlogRedisCacheAOP>();
                cacheType.Add(typeof(BlogRedisCacheAOP));
            }

            if (AppSettings.app(new string[] { "AppSettings", "LogAOP", "Enabled" }).ObjToBool())
            {
                builder.RegisterType<BlogLogAOP>();
                cacheType.Add(typeof(BlogLogAOP));
            }


            builder.RegisterGeneric(typeof(BaseRepository<>)).As(typeof(IBaseRepository<>)).InstancePerDependency(); //注册仓储
            builder.RegisterGeneric(typeof(BaseService<>)).As(typeof(IBaseServices<>)).InstancePerDependency();     //注册服务

            // 获取 Service.dll 程序集服务，并注册
            var assemblysServices = Assembly.LoadFrom(servicesDllFile);
            builder.RegisterAssemblyTypes(assemblysServices)
                .Where(t => t.Name.EndsWith("Services") && t.GetCustomAttributes<CachingInterceptorAttribute>().Any())
                .AsImplementedInterfaces()
                .InstancePerDependency()
                .PropertiesAutowired()
                .EnableInterfaceInterceptors()       //引用Autofac.Extras.DynamicProxy;
                .InterceptedBy(cacheType.ToArray()); //允许将拦截器服务的列表分配给注册。

            builder.RegisterAssemblyTypes(assemblysServices)
                .Where(t => t.Name.EndsWith("Services") && !t.GetCustomAttributes<CachingInterceptorAttribute>().Any())
                .AsImplementedInterfaces()
                .InstancePerDependency();

            ////只拦截特定服务
            //builder.RegisterType<AdvertisementServices>().As<IAdvertisementServices>();
            //builder.RegisterType<BlogArticleServices>().As<IBlogArticleServices>().InterceptedBy(typeof(BlogCacheAOP)).EnableInterfaceInterceptors();

            // 获取 Repository.dll 程序集服务，并注册
            var assemblysRepository = Assembly.LoadFrom(repositoryDllFile);
            builder.RegisterAssemblyTypes(assemblysRepository)
                .AsImplementedInterfaces()
                .PropertiesAutowired()
                .InstancePerDependency();

            //builder.RegisterType<UnitOfWorkManage>().As<IUnitOfWorkManage>()
            //    .AsImplementedInterfaces()
            //    .InstancePerLifetimeScope()
            //    .PropertiesAutowired();

            #endregion

            #region 没有接口层的服务层注入

            //因为没有接口层，所以不能实现解耦，只能用 Load 方法。
            //注意如果使用没有接口的服务，并想对其使用 AOP 拦截，就必须设置为虚方法
            //var assemblysServicesNoInterfaces = Assembly.Load("Blog.Core.Services");
            //builder.RegisterAssemblyTypes(assemblysServicesNoInterfaces);

            #endregion

            #region 没有接口的单独类，启用class代理拦截

            //只能注入该类中的虚方法，且必须是public
            //这里仅仅是一个单独类无接口测试，不用过多追问
            //builder.RegisterAssemblyTypes(Assembly.GetAssembly(typeof(Love)))
            //    .EnableClassInterceptors()
            //    .InterceptedBy(cacheType.ToArray());

            #endregion

            #region 单独注册一个含有接口的类，启用interface代理拦截

            //不用虚方法
            //builder.RegisterType<AopService>().As<IAopService>()
            //   .AsImplementedInterfaces()
            //   .EnableInterfaceInterceptors()
            //   .InterceptedBy(typeof(BlogCacheAOP));

            #endregion

            #region 上面有开关省略写法
            //#region AOP拦截 
            //    builder.RegisterType<BlogLogAOP>();//可以直接替换其他拦截器！一定要把拦截器进行注册
            //    var assemblysServices2 = Assembly.Load("EmployeeCard.Services");
            //    builder.RegisterAssemblyTypes(assemblysServices2)
            //             .AsImplementedInterfaces()
            //             .InstancePerLifetimeScope()
            //             .EnableInterfaceInterceptors()//引用Autofac.Extras.DynamicProxy;
            //             .InterceptedBy(typeof(BlogLogAOP));//可以直接替换拦截器
            //#endregion

            //#region AOP拦截缓存
            //    builder.RegisterType<BlogCacheAOP>();//注册缓存拦截器
            //    var assemblysServices3 = Assembly.Load("EmployeeCard.Services");
            //    builder.RegisterAssemblyTypes(assemblysServices3)
            //             .AsImplementedInterfaces()
            //             .InstancePerLifetimeScope()
            //             .EnableInterfaceInterceptors()//引用Autofac.Extras.DynamicProxy;
            //             .InterceptedBy(typeof(BlogCacheAOP));//可以直接替换拦截器
            //#endregion
            #endregion

        }
    }
}
